<template>
  <div class="container">
    <!-- <n-menu style="width: 400px" :options="treeList" accordion /> -->
    <div class="tableStyle">
      <n-button
      style="margin: 20px;float:right"
      size="small"
        @click="
          () => {
            model.name = ''
            model.route = ''
            model.type = 'add'
            model.key = ''
            showDialog = true
          }
        "
        >新增</n-button
      >
      <n-data-table
        ref="tableRef"
        style="width: 100%; height: 100%"
        :columns="columns"
        :data="treeList"
        :row-key="rowKey"
      />
    </div>
    <div style="width: 300px;padding: 30px 20px;" v-show="model.type">
      <h2>{{ model.type === 'add' ? '新增' : '编辑' }}</h2>
      <n-form ref="formRef" :model="model" :rules="rules">
        <n-form-item path="name" label="路由名称">
          <n-input v-model:value="model.name" type="text" />
        </n-form-item>
        <n-form-item path="route" label="路由地址">
          <n-input v-model:value="model.route" type="text" />
        </n-form-item>
        <n-button @click="submit">提交</n-button>
      </n-form>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, h, reactive, computed } from 'vue'
import type { DefaultMenu } from '@/type/defaultMenu'
import type { DataTableColumns } from 'naive-ui'
import { NButton } from 'naive-ui'
import menuList from '@/mock/defaultMenu'

let treeList = ref<DefaultMenu[]>([])
const transformTree = (data: DefaultMenu[]) => {
  const map = new Map()
  const rootNodes: DefaultMenu[] = []

  for (const item of data) {
    map.set(item.route, item)
  }

  data.forEach((item) => {
    if (item.parentRoute === '') {
      rootNodes.push(item)
    } else {
      const parent = map.get(item.parentRoute)
      if (parent) {
        if (!parent.children) {
          parent.children = []
        }
        parent.children.push(item)
      }
    }
  })

  return rootNodes
}
const rowKey = (row: DefaultMenu) => {
  return row.id
}
const columns: DataTableColumns<DefaultMenu> = [
  {
    title: 'id',
    key: 'id',
    titleAlign: 'center',
  },
  {
    title: '菜单名称',
    key: 'name'
  },
  {
    title: '菜单url',
    key: 'route'
  },
  {
    title: 'parentId',
    key: 'parentId',
    render(row) {
      return h('div', row.parentId || "——")
    }
  },
  {
    title: '操作',
    key: 'actions',
    titleAlign: 'center',
    width: 200,
    render(row) {
      return h('div', {
        style: {
          display: "flex",
          justifyContent: "space-around"
        }
      },[
        h(
          NButton,
          {
            onClick: () => {
              model.name = row.name
              model.route = row.route
              model.type = "edit"
              model.key = row.id
            },
            size: 'small',
          },
          {
            default: () => '编辑'
          }
        ),
        h(
          NButton,
          {
            onClick: () => {
              model.name = ""
              model.route = ""
              model.key = row.id
              model.type = "add"
            },
            size: 'small',
          },
          {
            default: () => '新增'
          }
        ),
        h(
          NButton,
          {
            onClick: () => deleteRoute(row),
            size: 'small'
          },
          {
            default: () => '删除'
          }
        )
      ])
    }
  }
]

onMounted(() => {
  treeList.value = []
  treeList.value = transformTree(menuList)
  console.log(treeList.value)
})

// 弹窗编辑
const showDialog = ref(false)
const formRef = ref(null), model = reactive({
  name: '',
  route: "",
  type: "",
  key: "",
}), rules = reactive({
  name: [
        {
          required: true,
          message: '请输入路由名称'
        }
      ],
  route: [
        {
          required: true,
          message: '请输入路由地址'
        }
      ],
})

const tableRef = ref()
const submit = () => {
  // 根据 type 判断表单的类型是新增还是编辑，此处 add 对应新增
  if(model.type === "add") {
    if(model.key) {
      // 此处的 key 对应点击行的 id，获取点击行
      const tempCase = findCase(treeList.value, model.key)
      if(tempCase && !tempCase.children) {
        tempCase.children = []
      }
      tempCase?.children?.push({
        id: new Date().getTime().toString(),
        route: model.route,
        name: model.name,
        sort: tempCase.children.length,
        parentRoute: model.key,
        parentId: tempCase.id
      })
    } else {
      treeList.value.push({
        id: new Date().getTime().toString(),
        route: model.route,
        name: model.name,
        sort: treeList.value.length,
        parentRoute: "",
        parentId: ""
      })
    }
  } else {
    // 编辑功能
    // 此处的 key 对应点击行的 id
    const tempCase = findCase(treeList.value, model.key)
    if(tempCase) {
      tempCase.name = model.name
      tempCase.route = model.route
    }
  }
}

// 树节点操作

// 删除节点
const deleteRoute = (row: DefaultMenu) => {
  const parent = findCase(treeList.value, row.parentId)
  if(parent && parent.children) {
    const index = parent.children.findIndex(item => item.id === row.id)
    if(index>-1) {
      parent.children.splice(index, 1)
    }
  } else {
    const index = treeList.value.findIndex(item => item.id === row.id)
    if(index>-1) {
      treeList.value.splice(index, 1)
    }
  }
}

// 增加节点
const addRouter = (row: DefaultMenu) => {
  row.children?.push({
    id: "",
    route: '',
    parentId: row.id,
    parentRoute: row.route,
    name: '',
    sort: row.children.length,
  })
}

// 工具函数
type FindParent = (nodes: DefaultMenu[], route: String) => DefaultMenu | null
type FindCase = (nodes: DefaultMenu[], key: String) => DefaultMenu | null
const findParent:FindParent = (nodes, route) => {
  for (const node of nodes) {
    if(node.route === route) {
      return node
    }
    if(node.children) {
      const found = findParent(node.children, route)
      if(found) {
        return found
      }
    }
  }
  return null
}

const findCase:FindCase = (tree, id) => {
  for (const item of tree) {
    if(item.id === id) {
      return item
    }
    if(item.children) {
      const found = findCase(item.children, id)
      if(found) {
        return found
      }
    }
  }
  return null
}


</script>

<style scoped>
.container {
  width: 100vw;
  height: 100vh;
  display: flex;
}
.tableStyle {
  width: 700px;
}
</style>
